package com.css.upms.biz.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.css.common.core.constent.CommonConstant;
import com.css.common.core.datascope.DataScope;
import com.css.common.core.utils.R;
import com.css.common.security.utils.SecurityUtil;
import com.css.upms.api.dto.UserDTO;
import com.css.upms.api.dto.UserPasswordDTO;
import com.css.upms.api.dto.UserQueryDTO;
import com.css.upms.api.entity.*;
import com.css.upms.api.vo.MenuVo;
import com.css.upms.api.vo.UserInfo;
import com.css.upms.api.vo.UserVo;
import com.css.upms.biz.mapper.SysUserMapper;
import com.css.upms.biz.service.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户信息表
 *
 * @author hanyx
 * @date 2019-05-03 01:02:03
 */
@Slf4j
@Service("sysUserService")
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    private final PasswordEncoder passwordEncoder;
    private final SysMenuService sysMenuService;
    private final SysRoleService sysRoleService;
    private final SysDeptService sysDeptService;
    private final SysUserRoleService sysUserRoleService;
    private final SysUserDeptService sysUserDeptService;

    /**
     * 用户信息表简单分页查询
     *
     * @param sysUser 用户信息表
     * @return
     */
    @Override
    public IPage<SysUser> getSysUserPage(Page<SysUser> page, SysUser sysUser) {
        return baseMapper.getSysUserPage(page, sysUser);
    }

    /**
     * 查询用户的全部信息
     *
     * @param sysUser 用户
     * @return
     */
    @Override
    public UserInfo getUserInfo(SysUser sysUser) {
        UserInfo userInfo = new UserInfo();
        userInfo.setSysUser(sysUser);
        //设置角色列表  （ID）
        List<String> roleIds = sysRoleService.listRolesByUserId(sysUser.getUserId())
                .stream()
                .map(SysRole::getRoleId)
                .collect(Collectors.toList());
        userInfo.setRoles(roleIds.toArray(new String[0]));

        //设置权限列表（menu.permission）
        Set<String> permissions = new HashSet<>();
        roleIds.forEach(roleId -> {
            List<String> permissionList = sysMenuService.getMenuByRoleId(roleId)
                    .stream()
                    .filter(menuVo -> StringUtils.isNotEmpty(menuVo.getPermission()))
                    .map(MenuVo::getPermission)
                    .collect(Collectors.toList());
            permissions.addAll(permissionList);
        });
        userInfo.setPermissions(permissions.toArray(new String[0]));
        return userInfo;
    }

    @Override
    public UserInfo getUserInfo(String username) {
        SysUser user = this.getOne(Wrappers.<SysUser>query()
                .lambda().eq(SysUser::getUsername, username)
                .eq(SysUser::getDelFlag, CommonConstant.STATUS_NORMAL));
        if (user == null) {
            return null;
        }
        return getUserInfo(user);
    }

    /**
     * 分页查询用户信息（含有角色信息）
     *
     * @param page    分页对象
     * @param userDTO 参数列表
     * @return
     */
    @Override
    public IPage getUserWithRolePage(Page page, UserQueryDTO userDTO) {
        DataScope dataScope = sysDeptService.getDataScope(SecurityUtil.getUser().getId());
        return baseMapper.getUserVosPage(page, userDTO, dataScope);
    }


    /**
     * 删除用户
     *
     * @param sysUser 用户
     * @return Boolean
     */
    @Override
    @CacheEvict(value = "user_details", key = "#sysUser.username")
    public Boolean removeUserById(SysUser sysUser) {
        sysUserRoleService.removeRoleByUserId(sysUser.getUserId());
        this.removeById(sysUser.getUserId());
        return Boolean.TRUE;
    }

    @Override
    @CacheEvict(value = "user_details", key = "#userDto.username")
    public R updateUserPassword(UserPasswordDTO userDto, boolean adminFlag) {

        SysUser sysUser = baseMapper.selectOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, userDto.getUsername()));
        if (adminFlag) {
            sysUser.setPassword(passwordEncoder.encode(userDto.getNewpassword1()));
        } else {
            if (StringUtils.isBlank(userDto.getPassword())) {
                return R.buildError("旧密码不能为空");
            }
            if (passwordEncoder.matches(userDto.getPassword(), sysUser.getPassword())) {
                sysUser.setPassword(passwordEncoder.encode(userDto.getNewpassword1()));
            } else {
                return R.buildError("原密码错误，修改失败");
            }
        }
        sysUser.setModifyTime(LocalDateTime.now());
        sysUser.setModifyBy(SecurityUtil.getUser().getId());
        return new R<>(this.updateById(sysUser));
    }

    @Override
    @CacheEvict(value = "user_details", key = "#userDto.username")
    public Boolean updateUser(UserDTO userDto) {
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(userDto, sysUser);
        sysUser.setModifyTime(LocalDateTime.now());
        sysUser.setModifyBy(SecurityUtil.getUser().getId());

        // 刷新CssUser中的部门ID
        if (StringUtils.isNotBlank(userDto.getDeptId()) && !StringUtils.equals(userDto.getDeptId(), SecurityUtil.getUser().getDeptId())) {

            // 清空原数据权限
            sysUserDeptService.remove(Wrappers.<SysUserDept>query()
                    .lambda().eq(SysUserDept::getUserId, userDto.getUserId()));
        }

        if (StringUtils.isNotBlank(userDto.getPassword())) {
            sysUser.setPassword(passwordEncoder.encode(userDto.getPassword()));
        }
        this.updateById(sysUser);

        if (CollectionUtils.isNotEmpty(userDto.getRole())) {
            sysUserRoleService.remove(Wrappers.<SysUserRole>update().lambda()
                    .eq(SysUserRole::getUserId, userDto.getUserId()));

            userDto.getRole().forEach(roleId -> {
                SysUserRole userRole = new SysUserRole();
                userRole.setUserId(sysUser.getUserId());
                userRole.setRoleId(roleId);
                userRole.insert();
            });
        }
        return Boolean.TRUE;
    }

    /**
     * 通过ID查询用户信息
     *
     * @param userDTO
     * @return 用户信息
     */
    @Override
    public UserVo getUserVo(UserQueryDTO userDTO) {
        return baseMapper.getUserVo(userDTO);
    }

    /**
     * 查询上级部门的用户信息
     *
     * @param username 用户名
     * @return R
     */
    @Override
    public List<SysUser> listAncestorUsersByUsername(String username) {
        SysUser sysUser = this.getOne(Wrappers.<SysUser>query().lambda()
                .eq(SysUser::getUsername, username));

        SysDept sysDept = sysDeptService.getById(sysUser.getDeptId());
        if (sysDept == null) {
            return null;
        }
        String parentId = sysDept.getParentId();
        return this.list(Wrappers.<SysUser>query().lambda()
                .eq(SysUser::getDeptId, parentId));
    }

    /**
     * 保存用户信息
     *
     * @param userDto DTO 对象
     * @return success/fail
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveUser(UserDTO userDto) {
        String username = userDto.getUsername();
        if (StringUtils.isBlank(username)) {
            return R.buildError("登录账号 不能为空");
        }

        SysUser checkUser = baseMapper.selectOne(Wrappers.<SysUser>query().lambda()
                .eq(SysUser::getUsername, username));

        if (checkUser != null) {
            return R.buildError("登录账号 已存在");
        }

        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(userDto, sysUser);
        sysUser.setDelFlag(CommonConstant.STATUS_NORMAL);
        sysUser.setPassword(passwordEncoder.encode(userDto.getPassword()));
        sysUser.setCreateBy(SecurityUtil.getUser().getId());
        sysUser.setCreateTime(LocalDateTime.now());
        baseMapper.insert(sysUser);
        List<SysUserRole> userRoleList = userDto.getRole()
                .stream().map(roleId -> {
                    SysUserRole userRole = new SysUserRole();
                    userRole.setUserId(sysUser.getUserId());
                    userRole.setRoleId(roleId);
                    return userRole;
                }).collect(Collectors.toList());
        sysUserRoleService.saveBatch(userRoleList);
        return new R(Boolean.TRUE);
    }

}
